package com.jlkf.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.jlkf.common.Constant;
import com.jlkf.common.googleMap.Location;
import com.jlkf.common.googleMap.SnappedPoints;
import com.jlkf.common.redis.service.JedisClient;
import com.jlkf.dao.CarCaculationPointChargesMapper;
import com.jlkf.dao.CityRecordMapper;
import com.jlkf.dao.GisRecordMapper;
import com.jlkf.dao.UserMapper;
import com.jlkf.pojo.CarCaculationPointCharges;
import com.jlkf.pojo.CityRecord;
import com.jlkf.pojo.GisRecord;
import com.jlkf.pojo.User;
import com.jlkf.service.GisRecordService;
import com.jlkf.service.OrderItemsService;
import com.jlkf.service.util.Distance;
import com.jlkf.service.util.RegexUtil;
import com.jlkf.service.util.StringTools;
import com.platform.server.response.response.pojo.ReturnData;
import com.platform.server.util.HttpRequestUtil;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@Service
public class GisRecordServiceImpl implements GisRecordService{

	@Autowired
	private GisRecordMapper gisRecordMapper;
	@Autowired
	private CityRecordMapper cityRecordMapper;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private JedisClient jedisClient;
	@Autowired
	private CarCaculationPointChargesMapper carCaculationPointChargesMapper;
	@Autowired
	private JedisPool jedisPool; 
	@Autowired
   private OrderItemsService orderItemsService;
	
	//首页通过经纬度查询附近的车辆
	@Override
	public ReturnData getPosition(String lng, String lat, String cityName) {
		Map<String,Object> map = new HashMap<>();
		if(!StringTools.isEmail(cityName)){
		map.put("cityName", cityName);	
		}
		Long cityId=null;
		try {
			List<CityRecord> list = cityRecordMapper.getList(map);//查询用户附近的司机
			List<Long> driverIds = new ArrayList<>();
			 if(list.size()>0){
				 cityId=list.get(0).getId();
			 }
			 map.put("cityId", cityId);
			 map.put("identity", 2);
			 map.put("isOnline", 1);
			 List<User> luser=userMapper.getLogin(map);//查询服务该城市的司机
			 for(User u:luser){
				 driverIds.add(u.getId());
			 }
			 if(driverIds.size()>0){
				 map.put("driverIds", driverIds); 
			 }
			 List<GisRecord> grlist=gisRecordMapper.selectByDriverId(map);//查询这个城市的司机的目前位置
			 return new ReturnData(grlist,200,"success");
		} catch (Exception e) {
			e.printStackTrace();
			return new ReturnData(500,"Wow, that's wrong");
		}
	}

	/**
	 * 首页查询附近的车辆
	 * @param lng 经度
	 * @param lat 纬度
	 * @param cityName 城市名称
	 * @return
	 */
	@Override
	public ReturnData getDriverPosition(Long driverId) {
		Map<String,Object> map = new HashMap<>();
		Long[] driverIds={driverId};
		map.put("driverIds", driverIds);
		 List<GisRecord> list=gisRecordMapper.selectByDriverId(map);
		 GisRecord gr = null;
		 if(list.size()>0){
			 gr =  list.get(0);
		 }
		try {
			return new ReturnData(gr,200,"success");
		} catch (Exception e) {
			e.printStackTrace();
			return new ReturnData(500,"Wow, that's wrong");
		}
	}
	
	
	//司机上传当前他的经纬度
	@Override
	public Object uploadDriverPosition(String json) {
		GisRecord gr = StringTools.json2Obj(json, GisRecord.class);
		if(gr==null){
			return new ReturnData(201,"The parameter list cannot be empty！");
		}
		Jedis jedis = null;
		Map<String,Object> map = new HashMap<>();
		String [] d={gr.getDriverId()};
		map.put("driverIds", d);
		String lastlatLon1="";String lastlatLon2="";Double mileage=0.0;
		if(jedis==null){
			jedis =jedisPool.getResource();
		}
		try {
			//查询司机是否有服务过 司机的经纬度同步表
			 List<GisRecord> lists=gisRecordMapper.selectByDriverId(map);
			 if(lists.size()>0){
				 gr.setId(lists.get(0).getId());
				 gr.setUpTime(new Date());
				 JSONArray ja = JSONArray.fromObject(gr.getPosition());
				 gr.setPosition(ja.toString());
				 int num=gisRecordMapper.updateByPrimaryKeySelective(gr);
				/* if(num==0){
					 return new ReturnData(201,"Upload failed");
				 }*/
			 }else{
				 gr.setUpTime(new Date());
				 int num=gisRecordMapper.insertSelective(gr);
				/* if(num==0){
					 return new ReturnData(201,"Upload failed");
				 }*/
			 }
			
			if(!RegexUtil.isNull(gr.getOrderId())){
				 JSONArray ja1 = JSONArray.fromObject(gr.getPosition());
				 List<String> StringList = JSONArray.toList(ja1, String.class);
				
				 String last= StringList.get(StringList.size()-1);//最后一个点
				 String[] lastlist=last.split(",");
				String lastPoint=lastlist[1]+","+lastlist[0];//将经纬度转换为纬经度
				
				String lastLatitudeAndLongitude =jedis.hget("lastLatitudeAndLongitude",gr.getOrderId()+"");//账单确认时，用于计算里程的点
				if(!StringTools.isEmpty(lastLatitudeAndLongitude)){//该订单是否有存之前的点
					 List<String> StringLists = JSONArray.toList(JSONArray.fromObject(lastLatitudeAndLongitude), String.class);
					 StringLists.add(lastPoint);//将最后一个点存入最终需要计算的数组中
					 JSONArray list = JSONArray.fromObject(StringLists);
					 jedis.hset("lastLatitudeAndLongitude",gr.getOrderId()+"",list.toString());
				}else{
					 List<String> StringLists =new ArrayList<>();
					 StringLists.add(lastPoint);
					 JSONArray list = JSONArray.fromObject(StringLists);
					 jedis.hset("lastLatitudeAndLongitude",gr.getOrderId()+"",list.toString());
				}
				//从缓存中取内容
				String result =jedis.hget("order",gr.getOrderId()+"");
				String MessagePoint =jedis.hget("MessagePoint",gr.getOrderId()+"");//校对的点
				if(!StringTools.isEmpty(MessagePoint)){//校对里程的点数据
					 List<String> StringLists = JSONArray.toList(JSONArray.fromObject(MessagePoint), String.class);
					 if(StringLists.size()>=50){
						 List<String> arr= rectifying(StringLists);//校对里程
						 JSONArray ja1s=JSONArray.fromObject(arr);
						 if(!StringTools.isEmpty(result)){
							//把字符串转换成list
								JSONArray ja = JSONArray.fromObject(result);
								 ja.addAll(ja1s);//将新上传的经纬度追加到缓存中
								JSONArray content = JSONArray.fromObject(ja);
								String newContent = content.toString();
								jedis.hset("order", gr.getOrderId() + "", newContent);//重新存到缓存中
						 }else{
							 String newContent = ja1s.toString();
							 jedis.hset("order", gr.getOrderId() + "", newContent);//存到缓存中
						}
					 }
				}else{
					List<String> StringLists =new ArrayList<>();
					 StringLists.add(lastPoint);
					 JSONArray list = JSONArray.fromObject(StringLists);
					 jedis.hset("MessagePoint",gr.getOrderId()+"",list.toString());
				}
						if (!StringUtils.isEmpty(result)) {
							//把字符串转换成list
							JSONArray ja = JSONArray.fromObject(result);
							 ja.addAll(ja1);//将新上传的经纬度追加到缓存中
							JSONArray content = JSONArray.fromObject(ja);
							String newContent = content.toString();
							jedis.hset("order", gr.getOrderId() + "", newContent);//重新存到缓存中
						}else{
							 String newContent = ja1.toString();
							 jedis.hset("order", gr.getOrderId() + "", newContent);//存到缓存中
						}
				//获取缓存中的收费站的信息 点点点点点点点点点点点点点点点点点点点点点点点点点点
				String point = jedis.hget("carCaculationPointCharges","carCaculationPointCharges_point");//点的收费
				String carCaculationPointListStr=jedis.hget("carCaculationPointCharges", "carCaculationPointChargesPoint");
				List<CarCaculationPointCharges> carCaculationPointChargesPoint = null;
				if(StringTools.isEmpty(carCaculationPointListStr)){
					Map<String,Object> map1 = new HashMap<>();
					map1.put("type", 1);
					carCaculationPointChargesPoint = carCaculationPointChargesMapper.getList(map1);
					JSONArray jp=JSONArray.fromObject(carCaculationPointChargesPoint);
					jedis.hset("carCaculationPointCharges","carCaculationPointChargesPoint",jp.toString());
				}
				String carCaculationPointListStrLine=jedis.hget("carCaculationPointCharges", "carCaculationPointListLine");
				List<CarCaculationPointCharges> carCaculationPointListLine = null;
				if(StringTools.isEmpty(carCaculationPointListStr)){
					Map<String,Object> map1 = new HashMap<>();
					map1.put("type", 1);
					carCaculationPointListLine = carCaculationPointChargesMapper.getList(map1);
					JSONArray jp=JSONArray.fromObject(carCaculationPointListLine);
					jedis.hset("carCaculationPointCharges","carCaculationPointListLine",jp.toString());
				}
				if(!StringUtils.isEmpty(point)){//如果有点的数据
//					JSONArray ja_point = JSONArray.fromObject(point);//存在缓存中数据结构为：[{"id":1,"position":""}]
//					List<CarCaculationPointCharges> ccpclist=JSONArray.toList(ja_point, CarCaculationPointCharges.class);
					for(CarCaculationPointCharges cc:carCaculationPointChargesPoint){
						String position =cc.getPosition();//后台配置的收费站的经纬度点
						String[] pos=position.split(",");
					    double pos1=Double.parseDouble(pos[0]);	double pos2=Double.parseDouble(pos[1]);//经度 纬度
					    for(String str:StringList){//遍历当前上传司机上传的经纬度 遍历每一个点 比较是否距离收费点
					    	String[] endpos = str.split(",");
					    	double endpos1=Double.parseDouble(endpos[0]);double endpos2=Double.parseDouble(endpos[1]);
					    	double len=	Distance.getDistance(pos1, pos2, endpos1, endpos2);//当前经纬与司机上传的经纬度<50米 则需要收费
					    	if(len<=50){//小于50米才算经过该收费点
					    		String carCaculationPointCharges_point=  jedis.hget("carCaculationPointCharges","carCaculationPointCharges_point_"+gr.getOrderId());//获取之前是否有收费点记录
					    	if(!StringTools.isEmpty(carCaculationPointCharges_point)){
					    		if(carCaculationPointCharges_point.indexOf(str)==-1){//判断我存的收费点是否包含了该收费 ，以免重复
					    			JSONArray jpoint = JSONArray.fromObject(carCaculationPointCharges_point);
						    		JSONArray jpoint1 = JSONArray.fromObject(position);//将经过的收费点 经纬度记录下来 后期结算时直接使用经纬度去查询
						    		jpoint.addAll(jpoint1);//改收费的点存到缓存中
										JSONArray content = JSONArray.fromObject(jpoint);
										String newContent = content.toString();
										jedis.hset("carCaculationPointCharges", "carCaculationPointCharges_point_"+gr.getOrderId() + "", newContent);//重新存到缓存中
					    		}
					    	 }else{//如果缓存中不存在该订单的收费站信息  
					    		 JSONArray jpoint1 = JSONArray.fromObject(str);
					    			String newContent = jpoint1.toString();
					    			jedis.hset("carCaculationPointCharges", "carCaculationPointCharges_point_"+gr.getOrderId() + "", newContent);//重新存到缓存中
					    	 }
					    	}
					    }
					}
				}else{//如果缓存中没有收费站点的数据 查询使用
					for(CarCaculationPointCharges cc:carCaculationPointChargesPoint){
						String position =cc.getPosition();//后台配置的收费站的经纬度点
						String[] pos=position.split(",");
					    double pos1=Double.parseDouble(pos[0]);	double pos2=Double.parseDouble(pos[1]);//经度 纬度
					    for(String str:StringList){//遍历当前上传司机上传的经纬度 遍历每一个点 比较是否距离收费点
					    	String[] endpos = str.split(",");
					    	double endpos1=Double.parseDouble(endpos[0]);double endpos2=Double.parseDouble(endpos[1]);
					    	double len=	Distance.getDistance(pos1, pos2, endpos1, endpos2);//当前经纬与司机上传的经纬度<50米 则需要收费
					    	if(len<=30){//小于50米才算经过该收费点
					    		String carCaculationPointCharges_point=  jedis.hget("carCaculationPointCharges","carCaculationPointCharges_point_"+gr.getOrderId());//获取之前是否有收费点记录
					    		JSONArray jpoint1 = JSONArray.fromObject(str);
				    			String newContent = jpoint1.toString();
				    			jedis.hset("carCaculationPointCharges", "carCaculationPointCharges_point_"+gr.getOrderId() + "", newContent);//重新存到缓存中
					    	}
					    }
					}
				}
				//  点点点点点点点点点点点点点点点点点点点点点点点点点点
				
				///线线 线线线线线线线线线线线线
				String line = jedis.hget("carCaculationPointCharges","carCaculationPointCharges_line");//线的收费
				
				if(!StringUtils.isEmpty(line)){//如果有线的数据
//					JSONArray ja_line_list = JSONArray.fromObject(line);
//					List<CarCaculationPointCharges> ccpclist=JSONArray.toList(ja_line_list, CarCaculationPointCharges.class);//获取走过收费点路段的记录
					  for(String str:StringList){//查询当前的我走过的经纬度 是否在我的收费段
						   String[] driverpos = str.split(",");
							double driverpos1=Double.parseDouble(driverpos[0]);double driverpos2=Double.parseDouble(driverpos[1]);//目前司机上传的多个经纬度
						   for(CarCaculationPointCharges cc:carCaculationPointListLine){//遍历我的收费表中的数据
								String position =cc.getPosition();//收费段的起点
								String[] pos=position.split(",");
								  double pos1=Double.parseDouble(pos[0]);	double pos2=Double.parseDouble(pos[1]);//收费点起点的经纬度   
								  String endPosition =cc.getEndPosition();//收费段的终点
								  String[] endPos=endPosition.split(",");
								  double endPos1=Double.parseDouble(endPos[0]);	double endPos2=Double.parseDouble(endPos[1]);//收费点出口的经纬度 
								  double starting_point=Distance.getDistance(driverpos1, driverpos2, pos1, pos2);//司机的当前位置与收费站起点做对比
								  double starting_end_point=Distance.getDistance(driverpos1, driverpos2, endPos1, endPos2);
								  if(starting_point<=30){
									  String carCaculationPointCharges_line=  jedis.hget("carCaculationPointCharges","carCaculationPointCharges_line_"+gr.getOrderId());//获取之前是否有收费点记录
								      if(!StringTools.isEmpty(carCaculationPointCharges_line)){
								    		  List<Map<String,List<String>>> lisMap = JSONArray.fromObject(carCaculationPointCharges_line);//数据结构如下[{"朗山路":["经纬度","经纬度"]}]
								    		  Map<String,List<String>> mapList = lisMap.get(lisMap.size()-1);
								    		 List<String> roadString= mapList.get(cc.getRoadName());//该高速上途径过的收费点经纬度
								    		 if(roadString!=null){
								    			 String roadStrin=roadString.toString();//改线路中
									    		 if(roadStrin.indexOf(str)==-1){//我的收费点线路中未出现该收费点
									    			 roadString.add(str);
								    				 roadString.add(endPosition);
									    		 }
								    		 }else{
								    			 roadString = new ArrayList<>();
//								    			 roadString.add(str);
								    			if(starting_end_point<=50){//结束距离小于50
								    				 roadString.add(str);
								    				 roadString.add(endPosition);
								    			} 
								    		 }
								    		 mapList.put(cc.getRoadName(), roadString);
								    		 lisMap.add(mapList);
								    		 JSONArray content = JSONArray.fromObject(lisMap);
								    		 String newContent = content.toString();
								    		 jedis.hset("carCaculationPointCharges", "carCaculationPointCharges_line_"+gr.getOrderId() + "", newContent);
								      }else{
								    	  List<Map<String,List<String>>> lisMap =new ArrayList<>();
								    	  Map<String,List<String>> mapList =new HashMap<>();
								    	  List<String> roadString=new ArrayList<>();
								    	  roadString.add(str);
								    	  roadString.add(endPosition);
								    	  mapList.put(cc.getRoadName(), roadString);
								    	  lisMap.add(mapList);
								    	  JSONArray content = JSONArray.fromObject(lisMap);
								    	 String newContent = content.toString();
								    	 jedis.hset("carCaculationPointCharges", "carCaculationPointCharges_line_"+gr.getOrderId() + "", newContent);
								      }
								  }
						   }
					  }
					}else{
						 for(String str:StringList){//查询当前的我走过的经纬度 是否在我的收费段
							   String[] driverpos = str.split(",");
								double driverpos1=Double.parseDouble(driverpos[0]);double driverpos2=Double.parseDouble(driverpos[1]);//目前司机上传的多个经纬度
							   for(CarCaculationPointCharges cc:carCaculationPointListLine){//遍历我的收费表中的数据
									String position =cc.getPosition();//收费段的起点
									String[] pos=position.split(",");
									  double pos1=Double.parseDouble(pos[0]);	double pos2=Double.parseDouble(pos[1]);//收费点起点的经纬度   
									  String endPosition =cc.getEndPosition();//收费段的终点
									  String[] endPos=endPosition.split(",");
									  double endPos1=Double.parseDouble(endPos[0]);	double endPos2=Double.parseDouble(endPos[1]);//收费点出口的经纬度 
									  double starting_point=Distance.getDistance(driverpos1, driverpos2, pos1, pos2);//司机的当前位置与收费站起点做对比
									  double starting_end_point=Distance.getDistance(driverpos1, driverpos2, endPos1, endPos2);
									  if(starting_point<=30){
										  List<Map<String,List<String>>> lisMap =new ArrayList<>();
								    	  Map<String,List<String>> mapList =new HashMap<>();
								    	  List<String> roadString=new ArrayList<>();
								    	  roadString.add(str);
								    	  roadString.add(endPosition);
								    	  mapList.put(cc.getRoadName(), roadString);
								    	  lisMap.add(mapList);
								    	  JSONArray content = JSONArray.fromObject(lisMap);
								    	 String newContent = content.toString();
								    	 jedis.hset("carCaculationPointCharges", "carCaculationPointCharges_line_"+gr.getOrderId() + "", newContent);
									  }
							   }
						  }
					}
			}
			
			 return new ReturnData(200,"Upload success");
		} catch (Exception e) {
			e.printStackTrace();
			return new ReturnData(500,"Wow, that's wrong");
		}finally {
			if(jedis!=null){
				jedis.close();
			}
		}
	}

	//整理Snap to Roads 接口
	public List<String> rectifying(List<String> result){
		StringBuffer sb = null;String param="";
		sb=new StringBuffer();List<String> arr=new ArrayList<>();
		for(String str:result){
			sb.append(str+"|");
		}
		if(sb.length()>0){
			param=sb.substring(0,sb.length()-1);
		}
		Map<String,Object> params=new HashMap<>();
		params.put("interpolate", "true");
		params.put("key", Constant.GOOGLE_API_KEY);
		params.put("path", param);
		try {
			String results = HttpRequestUtil.sendRequestByGet("https://roads.googleapis.com/v1/snapToRoads", params);
			if(!StringTools.isEmpty(results)){
				JSONObject googleResult=JSONObject.fromObject(results);
				JSONArray snappedPoints=JSONArray.fromObject(googleResult.get("snappedPoints"));
				for(int i=0;snappedPoints.size()>0;i++){
					JSONObject j = JSONObject.fromObject(snappedPoints.get(i));
					JSONObject jj = JSONObject.fromObject(j.get("location"));
					Location l = (Location) JSONObject.toBean(jj, Location.class);
					System.out.println(l.getLatitude());
					System.out.println(l.getLongitude());
					arr.add(l.getLongitude()+","+l.getLatitude());
				}
			}
			return arr;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return arr;
		}
	}
	
	@Override
	public Object getAllDriverPosition() {
		try {
			List<String> list = gisRecordMapper.selectAll();
			return new ReturnData(list,200,"gr_list");
		} catch (Exception e) {
			e.printStackTrace();
			return new ReturnData(500,"Wow, that's wrong");
		}
	}
	
	
}
